Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for detecting project ID. Fixes #97 #98

Merged
merged 1 commit into from
Oct 14, 2016
Merged

Add support for detecting project ID. Fixes #97 #98

merged 1 commit into from
Oct 14, 2016

Conversation

jmdobry
Copy link
Contributor

@jmdobry jmdobry commented Oct 1, 2016

Fixes #97

  • - Add support for detecting default project ID
    • - Detect from environment variables
    • - Detect from project_id field in GOOGLE_APPLICATION_CREDENTIALS key file
    • - Detect from Google Cloud SDK default config core/project setting
    • - Detect Compute Engine project ID
  • - Write tests

Before

auth.getApplicationDefault(err, authClient) {
  // ... 
});

After

auth.getApplicationDefault(err, authClient, projectId) {
  // ... 
});

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Oct 1, 2016
@stephenplusplus
Copy link
Contributor

What do you think about putting the project ID as a property on the authClient / a getter? Since users of the library are likely caching the authClient, it should be easier for them to just grab the projectId off of that object as opposed to additionally caching the projectId returned when they create the client.

@jmdobry
Copy link
Contributor Author

jmdobry commented Oct 1, 2016

They are related but still separate concerns. One is a set of credentials (a json key file), the other an identifier for a project. The auth object itself actually will have both of them cached. Today you can already access the cached credentials. My PR caches the project ID too. e.g.

// Get just the project ID
auth.getDefaultProjectId(function (err, projectId) {
  // The project ID has now been cached
  console.log(auth._cachedProjectId === projectId); // true
});
// Retrieve credentials and the project id
auth.getApplicationDefault(function (err, credentials, projectId) {
  // Both are cached
  console.log(auth._cachedCredential === credentials); // true
  console.log(auth._cachedProjectId === projectId); // true
});

This is how python is implementing it:

import google.auth

credentials, project_id = google.auth.default()

@stephenplusplus
Copy link
Contributor

I think the functionality of auto-detection of a project ID is quite helpful, and I think users will appreciate it, too. My thought is we should make it as easy as possible for them to get by putting it on the authClient instance so they don't have to "catch it before it's gone" (in the callback of the auth client fetcher).

But either way, google-auto-auth wraps this library, so I'll put it on the authClient that library returns, which should help us in our client libs.

@jmdobry
Copy link
Contributor Author

jmdobry commented Oct 1, 2016

catch it before it's gone

It won't be gone, it's cached on the auth object, just like the credentials. Once that callback is called they can access the cached project id on the auth instance they used to call getApplicationDefault, e.g. auth._cachedProjectId. Also, if the credentials object is actually a user's Service Account, it will already have a project_id field. I don't see anywhere in google-auth-library-nodejs where it actually modifies the default application credentials. It just loads them and caches them. I'm not sure one would want to attach the default project id to the loaded credentials, hence I cached them separate from each other.

But either way, google-auto-auth wraps this library, so I'll put it on the authClient that library returns, which should help us in our client libs.

👍, though personally I would have google-auto-auth do as I've done here and cache the project id on the google-auto-auth Auth instance, not the authClient value (which is actually the parsed key file). e.g. (from google-auto-auth):

function addScope(err, authClient, projectId) {
  if (err) {
    callback(err);
    return;
  }

  if (authClient.createScopedRequired && authClient.createScopedRequired()) {
    // ...
  }

  self.authClient = authClient;
  self.projectId = projectId;
  callback(null, authClient, projectId);
}

Then google-cloud-node or gax-nodejs can cache the credentials and projectId separately as they see fit. The two values are used for separate things. One for making an authorization header to pass with requests, the second to be a path parameter in requests (especially in the case of gax-nodejs.)

@stephenplusplus
Copy link
Contributor

it's cached on the auth object, just like the credentials.

I guess all I'm really saying is it shouldn't be "private". In JS, the leading _ tells developers not to rely on this value. And it tells contributors to this library that they can change the purpose of that property or remove it without being concerned it would break users' code.

  self.authClient = authClient;
  self.projectId = projectId;

Yep, that's exactly how I would do it :)

@jmdobry
Copy link
Contributor Author

jmdobry commented Oct 1, 2016

So perhaps we should also add synchronous getters to google-auth-library-nodejs for the credentials and projectId

@stephenplusplus
Copy link
Contributor

Can we also read the project_id from a service account keyfile?

@jmdobry
Copy link
Contributor Author

jmdobry commented Oct 3, 2016

@stephenplusplus
Copy link
Contributor

Is that in the case I don't have gcloud SDK installed at all, and I just provide a JSON key file?

@jmdobry
Copy link
Contributor Author

jmdobry commented Oct 3, 2016

Yeah, newer Service Account key files have a project_id field. This PR looks for a projectId in following places (in order of precedence):

  • GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT env var
  • project_id field of Service Account key file pointed to by GOOGLE_APPLICATION_CREDENTIALS
  • core/project field of default config file of Google Cloud SDK
  • GCE metadata server

@stephenplusplus
Copy link
Contributor

Does this library accept a key file path provided directly as a string, though? This is how I do it in google-auto-auth, but I'm not sure if I'm doing it in a way that this library intended to support.

@jmdobry
Copy link
Contributor Author

jmdobry commented Oct 3, 2016

Passing keyFile works as a consequence of google-auth-library-nodejs using gtoken under the hood. google-auth-library-nodejs itself does not actually do anything with keyFile.

getApplicationDefault and getDefaultProjectId don't look at keyFile at all.

@jmdobry jmdobry changed the title [DO NOT MERGE] Add support for detecting default project ID Add support for detecting project ID. Fixes #97 Oct 3, 2016
@coveralls
Copy link

coveralls commented Oct 3, 2016

Coverage Status

Coverage increased (+0.3%) to 92.673% when pulling 6921be6 on jmdobry:default-project into 02f5874 on google:master.

@stephenplusplus
Copy link
Contributor

@jmdobry what's the process for getting this shipped?

@stephenplusplus
Copy link
Contributor

// @tbetbetbe @jasonall

@jmdobry
Copy link
Contributor Author

jmdobry commented Oct 14, 2016

I'm not sure. Wishing I had write access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants